﻿// *----------------------------------------------------------------
// Copyright (C) 2017 通通优品
// 版权所有。
// 
// 类名：RedisDatabaseExtensions.cs
// 功能描述：TongTongMall.Redis
// 
// Create User：jym 2017/02/09
// 
// Edit User：UserName,EditTime
// Describe：Describe
// ----------------------------------------------------------------*/
using System;
using StackExchange.Redis;

namespace TongTongMall.Redis.Cache
{
    internal static class RedisDatabaseExtensions
    {
        public static void KeyDeleteWithPrefix(this IDatabase database, string prefix)
        {
            if (database == null)
            {
                throw new ArgumentException("Database cannot be null", "database");
            }

            if (string.IsNullOrWhiteSpace(prefix))
            {
                throw new ArgumentException("Prefix cannot be empty", "database");
            }

            database.ScriptEvaluate(@"
                local keys = redis.call('keys', ARGV[1]) 
                for i=1,#keys,5000 do 
                redis.call('del', unpack(keys, i, math.min(i+4999, #keys)))
                end", values: new RedisValue[] { prefix });
        }

        public static long GetNextSequence(this IDatabase database, string key, TimeSpan? timespan = null)
        {
            if (database == null)
            {
                throw new ArgumentException("Database cannot be null", "database");
            }

            if (string.IsNullOrWhiteSpace(key))
            {
                throw new ArgumentException("key cannot be empty", "database");
            }
            var incrSequence = database.ScriptEvaluate($@"
                local current
                current = redis.call(""{RedisCommands.Incr}"",KEYS[1]) 
                if tonumber(current)==1 then
                 redis.call(""{RedisCommands.Expire}"",KEYS[1],ARGV[1])
                end
                return current"
                , new RedisKey[] { key }, new RedisValue[] { (int)(timespan?.TotalSeconds ?? 1) }
                );
            if (incrSequence.IsNull)
            {
                return 0;
            }
            return (long)incrSequence;
        }

        public static int KeyCount(this IDatabase database, string prefix)
        {
            if (database == null)
            {
                throw new ArgumentException("Database cannot be null", "database");
            }

            if (string.IsNullOrWhiteSpace(prefix))
            {
                throw new ArgumentException("Prefix cannot be empty", "database");
            }

            var retVal = database.ScriptEvaluate("return table.getn(redis.call('keys', ARGV[1]))", values: new RedisValue[] { prefix });

            if (retVal.IsNull)
            {
                return 0;
            }

            return (int)retVal;
        }
    }
}
